Skip to content

[libc][math] Refactor asinhf implementation to header-only in src/__support/math folder. #150843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

bassiounix
Copy link
Contributor

@bassiounix bassiounix commented Jul 27, 2025

Copy link
Contributor Author

bassiounix commented Jul 27, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@bassiounix bassiounix requested a review from lntue July 27, 2025 17:13
@bassiounix bassiounix added libc bazel "Peripheral" support tier build system: utils/bazel cmake Build system in general and CMake in particular labels Jul 27, 2025 — with Graphite App
@llvmbot
Copy link
Member

llvmbot commented Jul 27, 2025

@llvm/pr-subscribers-libc

Author: Muhammad Bassiouni (bassiounix)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/150843.diff

9 Files Affected:

  • (modified) libc/shared/math.h (+1)
  • (added) libc/shared/math/asinhf.h (+23)
  • (modified) libc/src/__support/math/CMakeLists.txt (+14)
  • (added) libc/src/__support/math/asinhf.h (+125)
  • (modified) libc/src/math/generic/CMakeLists.txt (+1-6)
  • (modified) libc/src/math/generic/asinhf.cpp (+2-104)
  • (modified) libc/test/shared/CMakeLists.txt (+1)
  • (modified) libc/test/shared/shared_math_test.cpp (+1)
  • (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+15-8)
diff --git a/libc/shared/math.h b/libc/shared/math.h
index e01c8db81eb80..e0f00f52e9dc3 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -20,6 +20,7 @@
 #include "math/asin.h"
 #include "math/asinf.h"
 #include "math/asinf16.h"
+#include "math/asinhf.h"
 #include "math/erff.h"
 #include "math/exp.h"
 #include "math/exp10.h"
diff --git a/libc/shared/math/asinhf.h b/libc/shared/math/asinhf.h
new file mode 100644
index 0000000000000..c4a550902b708
--- /dev/null
+++ b/libc/shared/math/asinhf.h
@@ -0,0 +1,23 @@
+//===-- Shared asinhf function ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SHARED_MATH_ASINHF_H
+#define LLVM_LIBC_SHARED_MATH_ASINHF_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/asinhf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::asinhf;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ASINHF_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 105093887980d..13f46a13fe0d7 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -140,6 +140,20 @@ add_header_library(
     libc.src.__support.macros.properties.cpu_features
 )
 
+add_header_library(
+  asinhf
+  HDRS
+    asinhf.h
+  DEPENDS
+    .acoshf_utils
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.sqrt
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   asinf
   HDRS
diff --git a/libc/src/__support/math/asinhf.h b/libc/src/__support/math/asinhf.h
new file mode 100644
index 0000000000000..1c08a6e6651b7
--- /dev/null
+++ b/libc/src/__support/math/asinhf.h
@@ -0,0 +1,125 @@
+//===-- Implementation header for asinf -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF_H
+
+#include "acoshf_utils.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float asinhf(float x) {
+  using namespace acoshf_internal;
+  using FPBits_t = typename fputil::FPBits<float>;
+  FPBits_t xbits(x);
+  uint32_t x_u = xbits.uintval();
+  uint32_t x_abs = xbits.abs().uintval();
+
+  // |x| <= 2^-3
+  if (LIBC_UNLIKELY(x_abs <= 0x3e80'0000U)) {
+    // |x| <= 2^-26
+    if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
+      return static_cast<float>(LIBC_UNLIKELY(x_abs == 0)
+                                    ? x
+                                    : (x - 0x1.5555555555555p-3 * x * x * x));
+    }
+
+    double x_d = x;
+    double x_sq = x_d * x_d;
+    // Generated by Sollya with:
+    // > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16|], [|D...|],
+    //                 [0, 2^-2]);
+    double p = fputil::polyeval(
+        x_sq, 0.0, -0x1.555555555551ep-3, 0x1.3333333325495p-4,
+        -0x1.6db6db5a7622bp-5, 0x1.f1c70f82928c6p-6, -0x1.6e893934266b7p-6,
+        0x1.1c0b41d3fbe78p-6, -0x1.c0f47810b3c4fp-7, 0x1.2c8602690143dp-7);
+    return static_cast<float>(fputil::multiply_add(x_d, p, x_d));
+  }
+
+  const double SIGN[2] = {1.0, -1.0};
+  double x_sign = SIGN[x_u >> 31];
+  double x_d = x;
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+  // Helper functions to set results for exceptional cases.
+  auto round_result_slightly_down = [x_sign](float r) -> float {
+    return fputil::multiply_add(static_cast<float>(x_sign), r,
+                                static_cast<float>(x_sign) * (-0x1.0p-24f));
+  };
+  auto round_result_slightly_up = [x_sign](float r) -> float {
+    return fputil::multiply_add(static_cast<float>(x_sign), r,
+                                static_cast<float>(x_sign) * 0x1.0p-24f);
+  };
+
+  if (LIBC_UNLIKELY(x_abs >= 0x4bdd'65a5U)) {
+    if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
+      if (xbits.is_signaling_nan()) {
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits_t::quiet_nan().get_val();
+      }
+
+      return x;
+    }
+
+    // Exceptional cases when x > 2^24.
+    switch (x_abs) {
+    case 0x4bdd65a5: // |x| = 0x1.bacb4ap24f
+      return round_result_slightly_down(0x1.1e0696p4f);
+    case 0x4c803f2c: // |x| = 0x1.007e58p26f
+      return round_result_slightly_down(0x1.2b786cp4f);
+    case 0x4f8ffb03: // |x| = 0x1.1ff606p32f
+      return round_result_slightly_up(0x1.6fdd34p4f);
+    case 0x5c569e88: // |x| = 0x1.ad3d1p57f
+      return round_result_slightly_up(0x1.45c146p5f);
+    case 0x5e68984e: // |x| = 0x1.d1309cp61f
+      return round_result_slightly_up(0x1.5c9442p5f);
+    case 0x655890d3: // |x| = 0x1.b121a6p75f
+      return round_result_slightly_down(0x1.a9a3f2p5f);
+    case 0x65de7ca6: // |x| = 0x1.bcf94cp76f
+      return round_result_slightly_up(0x1.af66cp5f);
+    case 0x6eb1a8ec: // |x| = 0x1.6351d8p94f
+      return round_result_slightly_down(0x1.08b512p6f);
+    case 0x7997f30a: // |x| = 0x1.2fe614p116f
+      return round_result_slightly_up(0x1.451436p6f);
+    }
+  } else {
+    // Exceptional cases when x < 2^24.
+    if (LIBC_UNLIKELY(x_abs == 0x45abaf26)) {
+      // |x| = 0x1.575e4cp12f
+      return round_result_slightly_down(0x1.29becap3f);
+    }
+    if (LIBC_UNLIKELY(x_abs == 0x49d29048)) {
+      // |x| = 0x1.a5209p20f
+      return round_result_slightly_down(0x1.e1b92p3f);
+    }
+  }
+#else
+  if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
+    return x;
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+  // asinh(x) = log(x + sqrt(x^2 + 1))
+  return static_cast<float>(
+      x_sign * log_eval(fputil::multiply_add(
+                   x_d, x_sign,
+                   fputil::sqrt<double>(fputil::multiply_add(x_d, x_d, 1.0)))));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index d4d268cff97e8..f91feacbff54d 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3889,12 +3889,7 @@ add_entrypoint_object(
   HDRS
     ../asinhf.h
   DEPENDS
-    .explogxf
-    libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.multiply_add
-    libc.src.__support.FPUtil.polyeval
-    libc.src.__support.FPUtil.sqrt
-    libc.src.__support.macros.optimization
+    libc.src.__support.math.asinhf
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/asinhf.cpp b/libc/src/math/generic/asinhf.cpp
index 3aed3bc2c9cde..45023c8c6037c 100644
--- a/libc/src/math/generic/asinhf.cpp
+++ b/libc/src/math/generic/asinhf.cpp
@@ -7,112 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/asinhf.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/math/generic/common_constants.h"
-#include "src/math/generic/explogxf.h"
+#include "src/__support/math/asinhf.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-LLVM_LIBC_FUNCTION(float, asinhf, (float x)) {
-  using namespace acoshf_internal;
-  using FPBits_t = typename fputil::FPBits<float>;
-  FPBits_t xbits(x);
-  uint32_t x_u = xbits.uintval();
-  uint32_t x_abs = xbits.abs().uintval();
-
-  // |x| <= 2^-3
-  if (LIBC_UNLIKELY(x_abs <= 0x3e80'0000U)) {
-    // |x| <= 2^-26
-    if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
-      return static_cast<float>(LIBC_UNLIKELY(x_abs == 0)
-                                    ? x
-                                    : (x - 0x1.5555555555555p-3 * x * x * x));
-    }
-
-    double x_d = x;
-    double x_sq = x_d * x_d;
-    // Generated by Sollya with:
-    // > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16|], [|D...|],
-    //                 [0, 2^-2]);
-    double p = fputil::polyeval(
-        x_sq, 0.0, -0x1.555555555551ep-3, 0x1.3333333325495p-4,
-        -0x1.6db6db5a7622bp-5, 0x1.f1c70f82928c6p-6, -0x1.6e893934266b7p-6,
-        0x1.1c0b41d3fbe78p-6, -0x1.c0f47810b3c4fp-7, 0x1.2c8602690143dp-7);
-    return static_cast<float>(fputil::multiply_add(x_d, p, x_d));
-  }
-
-  const double SIGN[2] = {1.0, -1.0};
-  double x_sign = SIGN[x_u >> 31];
-  double x_d = x;
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-  // Helper functions to set results for exceptional cases.
-  auto round_result_slightly_down = [x_sign](float r) -> float {
-    return fputil::multiply_add(static_cast<float>(x_sign), r,
-                                static_cast<float>(x_sign) * (-0x1.0p-24f));
-  };
-  auto round_result_slightly_up = [x_sign](float r) -> float {
-    return fputil::multiply_add(static_cast<float>(x_sign), r,
-                                static_cast<float>(x_sign) * 0x1.0p-24f);
-  };
-
-  if (LIBC_UNLIKELY(x_abs >= 0x4bdd'65a5U)) {
-    if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
-      if (xbits.is_signaling_nan()) {
-        fputil::raise_except_if_required(FE_INVALID);
-        return FPBits_t::quiet_nan().get_val();
-      }
-
-      return x;
-    }
-
-    // Exceptional cases when x > 2^24.
-    switch (x_abs) {
-    case 0x4bdd65a5: // |x| = 0x1.bacb4ap24f
-      return round_result_slightly_down(0x1.1e0696p4f);
-    case 0x4c803f2c: // |x| = 0x1.007e58p26f
-      return round_result_slightly_down(0x1.2b786cp4f);
-    case 0x4f8ffb03: // |x| = 0x1.1ff606p32f
-      return round_result_slightly_up(0x1.6fdd34p4f);
-    case 0x5c569e88: // |x| = 0x1.ad3d1p57f
-      return round_result_slightly_up(0x1.45c146p5f);
-    case 0x5e68984e: // |x| = 0x1.d1309cp61f
-      return round_result_slightly_up(0x1.5c9442p5f);
-    case 0x655890d3: // |x| = 0x1.b121a6p75f
-      return round_result_slightly_down(0x1.a9a3f2p5f);
-    case 0x65de7ca6: // |x| = 0x1.bcf94cp76f
-      return round_result_slightly_up(0x1.af66cp5f);
-    case 0x6eb1a8ec: // |x| = 0x1.6351d8p94f
-      return round_result_slightly_down(0x1.08b512p6f);
-    case 0x7997f30a: // |x| = 0x1.2fe614p116f
-      return round_result_slightly_up(0x1.451436p6f);
-    }
-  } else {
-    // Exceptional cases when x < 2^24.
-    if (LIBC_UNLIKELY(x_abs == 0x45abaf26)) {
-      // |x| = 0x1.575e4cp12f
-      return round_result_slightly_down(0x1.29becap3f);
-    }
-    if (LIBC_UNLIKELY(x_abs == 0x49d29048)) {
-      // |x| = 0x1.a5209p20f
-      return round_result_slightly_down(0x1.e1b92p3f);
-    }
-  }
-#else
-  if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
-    return x;
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-  // asinh(x) = log(x + sqrt(x^2 + 1))
-  return static_cast<float>(
-      x_sign * log_eval(fputil::multiply_add(
-                   x_d, x_sign,
-                   fputil::sqrt<double>(fputil::multiply_add(x_d, x_d, 1.0)))));
-}
+LLVM_LIBC_FUNCTION(float, asinhf, (float x)) { return math::asinhf(x); }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index e93fbb9ffbbdf..77f3617841293 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -16,6 +16,7 @@ add_fp_unittest(
     libc.src.__support.math.asin
     libc.src.__support.math.asinf
     libc.src.__support.math.asinf16
+    libc.src.__support.math.asinhf
     libc.src.__support.math.erff
     libc.src.__support.math.exp
     libc.src.__support.math.exp10
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 51d38ecc22300..2e4450a9b40e8 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -42,6 +42,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
   EXPECT_FP_EQ(0x1.921fb6p+0, LIBC_NAMESPACE::shared::acosf(0.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::acoshf(1.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinf(0.0f));
+  EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinhf(0.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::erff(0.0f));
   EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::exp10f(0.0f));
   EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::expf(0.0f));
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index d424026c2723f..0e40d92cb5c97 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2231,6 +2231,20 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_asinhf",
+    hdrs = ["src/__support/math/asinhf.h"],
+    deps = [
+        ":__support_math_acoshf_utils",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_polyeval",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_sqrt",
+        ":__support_macros_config",
+        ":__support_macros_optimization",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_asinf",
     hdrs = ["src/__support/math/asinf.h"],
@@ -2829,14 +2843,7 @@ libc_math_function(
 libc_math_function(
     name = "asinhf",
     additional_deps = [
-        ":__support_fputil_fma",
-        ":__support_fputil_multiply_add",
-        ":__support_fputil_nearest_integer",
-        ":__support_fputil_polyeval",
-        ":__support_fputil_sqrt",
-        ":__support_macros_optimization",
-        ":common_constants",
-        ":explogxf",
+        ":__support_math_asinhf",
     ],
 )
 

@bassiounix bassiounix marked this pull request as ready for review July 27, 2025 17:14
@bassiounix bassiounix force-pushed the users/bassiounix/spr/refactor-math-functions-to-header-only branch 2 times, most recently from e0a7f4b to b06c93e Compare July 27, 2025 17:53
Copy link
Contributor Author

bassiounix commented Jul 28, 2025

Merge activity

  • Jul 28, 3:13 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 28, 3:14 PM UTC: @bassiounix merged this pull request with Graphite.

@bassiounix bassiounix merged commit 5bcbcf8 into main Jul 28, 2025
25 of 35 checks passed
@bassiounix bassiounix deleted the users/bassiounix/spr/refactor-math-functions-to-header-only branch July 28, 2025 15:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bazel "Peripheral" support tier build system: utils/bazel cmake Build system in general and CMake in particular libc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants